package com.ming.security.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 配置用户角色和接口之间的权限的关系,也可在xml中配置
 */
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;

    /**
     * 配置用户权限和接口路径的关系
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("加载授权配置...");
        http   .authorizeRequests()// 对请求进行验证
                .antMatchers("/static/**","index.html")
                .permitAll()// 所有请求

                .antMatchers("/level1/**")
                .hasRole("USER")

                .antMatchers("/level2/**")
                .hasRole("USER")
                .antMatchers("/level2/**")
                .hasRole("ADMIN")

                .antMatchers("/level3/**")
                .hasRole("ADMIN")

                .antMatchers("/level3/**")
                .hasAnyAuthority("SAVE")


                .anyRequest()// 其它未设置的所有请求
                .authenticated()// 需要进行认证

                .and()
                .formLogin()// 设置未授权请求跳转到登录页面
                .loginPage("/index.html")// 未授权跳转页面
                .loginProcessingUrl("/do/login.html")// 提交登录表单的地址
                .permitAll()// 登录页允许所有请求访问
                .usernameParameter("user")// 默认账号请求参数,登录表单中用户名对应的name
                .passwordParameter("password")
                .defaultSuccessUrl("/main.html")// 登录成功后默认前往的URL地址


                .and()
                .logout()
                .logoutUrl("/do/logout.html")
                .logoutSuccessUrl("/index.html")// 退出后前往的地址

                .and()
                .exceptionHandling()// 指定异常处理器
                .accessDeniedHandler(new AccessDeniedHandler() {// 设置拒绝访问前往的页面
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
                        request.setAttribute("message",e.getMessage());
                        request.getRequestDispatcher("/no_auth.html").forward(request,response);
                    }
                })
                .and()
                .csrf()
                .disable();// 禁用CSRF
    }

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        log.info("查询权限信息...");
        // 设置登录系统的账号和密码
        builder
                .userDetailsService(userDetailsService);
//                .inMemoryAuthentication()
//
//                .withUser("ming")
//                .password("95C90AA47733B9023C318D9914606339")// 设置用户名和密码
//                .roles("USER")// 设置账户角色
//                .authorities("EDIT")
//
//                .and()
//                .withUser("admin").password("21232F297A57A5A743894A0E4A801FC3" )// 明文
//                .authorities("SAVE","EDIT")
//                .roles("ADMIN").roles("USER")
//
//                .and()
//                .withUser("tom").password(new BCryptPasswordEncoder().encode("tom") )// 明文
//                .authorities("SAVE","EDIT");
////                .passwordEncoder(passwordEncoderService);// 选择明文方式则需要打开该注释,避免使用md5加密

    }
}
